/*-
 * Copyright (c) 2010, 2011, 2012, 2013, Columbia University
 * All rights reserved.
 *
 * This software was developed by Vasileios P. Kemerlis <vpk@cs.columbia.edu>
 * at Columbia University, New York, NY, USA, in June 2010.
 *
 * Georgios Portokalidis <porto@cs.columbia.edu> contributed to the
 * optimized implementation of tagmap_setn() and tagmap_clrn()
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Columbia University nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "libdft_api.h"
#include "tagmap.h"
#include "branch_pred.h"

#ifndef _WIN32

#ifdef	HUGE_TLB
#ifndef	MAP_HUGETLB
#define	MAP_HUGETLB	0x40000	/* architecture specific */
#endif
#define MAP_FLAGS	MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB
#else
#define MAP_FLAGS	MAP_PRIVATE | MAP_ANONYMOUS
#endif

#else

#endif


/*
 * tagmap
 *
 * the tagmap is the core data structure in libdft.
 * It keeps the tag information for the virtual address space
 * of a process. For the 32-bit x86 architecture, it is implemented
 * using a BITMAP_SZ MB bitmap.
 *
 * Every byte that is addressable in the 32-bit virtual address
 * space is represented using one bit on the tagmap.
 */

/*
 * initialize the tagmap; allocate space
 *
 * returns:	0 on success, 1 on error 
 */
int PIN_FAST_ANALYSIS_CALL
tagmap_alloc(void)
{
	return 0;
}

/*
 * dispose the tagmap; deallocate its space
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_free(void)
{
	_taint_map.clear();
}

/*
 * tag a byte on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_setb(size_t addr)
{
	_taint_map.set_bits(addr,1,true);
}

/*
 * untag a byte on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_clrb(size_t addr)
{
	_taint_map.set_bits(addr,1,false);}

/*
 * get the tag value of a byte from the tagmap
 *
 * @addr:	the virtual address
 *
 * returns:	the tag value (e.g., 0, 1,...)
 */
size_t PIN_FAST_ANALYSIS_CALL
tagmap_getb(size_t addr)
{
	return _taint_map.test_bits(addr,1);
}

/*
 * tag a word (i.e., 2 bytes) on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_setw(size_t addr)
{
	return _taint_map.set_bits(addr,2,true);
}

/*
 * untag a word (i.e., 2 bytes) on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_clrw(size_t addr)
{
	return _taint_map.set_bits(addr,2,false);
}

/*
 * get the tag value of a word (i.e., 2 bytes) from the tagmap
 *
 * @addr:	the virtual address
 *
 * returns:	the tag value (e.g., 0, 1,...)
 */
size_t PIN_FAST_ANALYSIS_CALL
tagmap_getw(size_t addr)
{
	return _taint_map.test_bits(addr,2);
}

/*
 * tag a long word (i.e., 4 bytes) on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_setl(size_t addr)
{
	_taint_map.set_bits(addr,4,true);
}

/*
 * untag a long word (i.e., 4 bytes) on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_clrl(size_t addr)
{
	_taint_map.set_bits(addr,4,false);
}

/*
 * get the tag value of a long word (i.e., 4 bytes) from the tagmap
 *
 * @addr:	the virtual address
 *
 * returns:	the tag value (e.g., 0, 1,...)
 */
size_t PIN_FAST_ANALYSIS_CALL
tagmap_getl(size_t addr)
{
	return _taint_map.test_bits(addr,4);
}

/*
 * tag a quad word (i.e., 8 bytes) on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_setq(size_t addr)
{
	_taint_map.set_bits(addr,8,true);
}

/*
 * untag a quad word (i.e., 8 bytes) on the virtual address space
 *
 * @addr:	the virtual address
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_clrq(size_t addr)
{
	_taint_map.set_bits(addr,8,false);
}

/*
 * get the tag value of a quad word (i.e., 8 bytes) from the tagmap
 *
 * @addr:	the virtual address
 *
 * returns:	the tag value (e.g., 0, 1,...)
 */
size_t PIN_FAST_ANALYSIS_CALL
tagmap_getq(size_t addr)
{
	return _taint_map.test_bits(addr,8);
}

/*
 * check if an arbitrary number of bytes on the virtual address space are set
 *
 * in case the number of bytes can be handled efficiently (e.g.,
 * tag a byte, word, long, or quad) then we use one the previous
 * functions. In all other cases, we try to align the number of
 * bits that needs to be checked for reusing the get{b, w, l ,q}()
 * functions as much as possible 
 *
 * @addr:	the virtual address
 * @num:	the number of bytes to check
 *
 * returns:	0 if clean, non-zero otherwise
 */
size_t PIN_FAST_ANALYSIS_CALL
tagmap_issetn(size_t addr, size_t num)
{
	return _taint_map.test_bits(addr,num);
}

/*
 * tag an arbitrary number of bytes on the virtual address space
 *
 * in case the number of bytes can be handled efficiently (e.g.,
 * tag a byte, word, long, or quad) then we use one the previous
 * functions. In all other cases, we try to align the number of
 * bits that needs to be asserted for reusing the set{b, w, l ,q}()
 * functions as much as possible 
 *
 * @addr:	the virtual address
 * @num:	the number of bytes to tag
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_setn(size_t addr, size_t num)
{
	_taint_map.set_bits(addr,num,true);
}

/*
 * untag an arbitrary number of bytes on the virtual address space
 *
 * @addr:	the virtual address
 * @num:	the number of bytes to untag
 */
void PIN_FAST_ANALYSIS_CALL
tagmap_clrn(size_t addr, size_t num)
{
	_taint_map.set_bits(addr,num,false);
}


